/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.rbac.service.account.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.je.auth.AuthLoginManager;
import com.je.common.auth.impl.PlatformOrganization;
import com.je.common.auth.impl.RealOrganizationUser;
import com.je.common.auth.impl.account.Account;
import com.je.common.auth.impl.role.Role;
import com.je.common.base.DynaBean;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.rpc.SystemSettingRpcService;
import com.je.common.base.util.ArrayUtils;
import com.je.common.base.util.DateUtils;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.rbac.exception.AccountException;
import com.je.rbac.rpc.AccountRpcService;
import com.je.rbac.service.account.RbacAccountService;
import com.je.rbac.service.organization.OrgType;
import com.je.rbac.service.organization.RbacOrganizationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

@Service
public class RbacAccountServiceImpl implements RbacAccountService {

    @Autowired
    private MetaService metaService;
    @Autowired
    private RbacOrganizationService organizationService;
    @Autowired
    private AuthLoginManager authLoginManager;
    @Autowired
    private SystemSettingRpcService systemSettingRpcService;
    @Autowired
    private AccountRpcService accountRpcService;

    @Override
    public PlatformOrganization findOrganizationById(String orgId) {
        return organizationService.buildById(orgId);
    }

    @Override
    public boolean checkUserStatusByAccountId(String accountId, int accountIdSize) throws AccountException {
        DynaBean accountBean = metaService.selectOne("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("JE_RBAC_ACCOUNT_ID", accountId));
        if (accountBean == null) {
            throw new AccountException("Can't find the account by id");
        }
        //若是公司员工类型，校验人员在职状态，部门状态，若该账号是外部机构 则直接判断机构状态.
        DynaBean orgBean = metaService.selectOne("JE_RBAC_ORG", ConditionsWrapper.builder().eq("JE_RBAC_ORG_ID", accountBean.getStr("SY_ORG_ID")));
        if (orgBean.getStr("JE_RBAC_ORG_ID").equals(OrgType.DEPARTMENT_ORG_ID.getCode())) {
            //判断人员在职离职状态；若在职就判断人员主部门状态。
            DynaBean userBean = metaService.selectOne("JE_RBAC_USER", ConditionsWrapper.builder().eq("JE_RBAC_USER_ID", accountBean.getStr("USER_ASSOCIATION_ID")));
            if (userBean.getStr("USER_EMPLOYEE_STATUS").equals("0")) {
                if (accountIdSize == 1) {
                    throw new AccountException("该账号关联的员工已离职，无法启用账号，请先修改员工状态！");
                } else {
                    throw new AccountException("该账号【" + accountBean.getStr("ACCOUNT_NAME") + "】关联的员工已离职，无法启用账号，请先修改员工状态！");
                }

            }
            //查主部门状态
            DynaBean userDeptBean = metaService.selectOne("JE_RBAC_DEPTUSER", ConditionsWrapper.builder().eq("DEPTUSER_MAIN_CODE", "1").eq("JE_RBAC_USER_ID", accountBean.getStr("USER_ASSOCIATION_ID")));
            if (userDeptBean.getStr("SY_STATUS").equals("0")) {
                if (accountIdSize == 1) {
                    throw new AccountException("该账号关联的主部门员工已被禁用，请先启用访问状态！");
                } else {
                    throw new AccountException("该账号【" + accountBean.getStr("ACCOUNT_NAME") + "】关联的主部门员工已被禁用，请先启用访问状态！");
                }
            }
        } else {
            //判断机构账号所属用户状态
            //获取到映射的资源表和资源表主键
            String tableCode = orgBean.getStr("ORG_RESOURCETABLE_CODE");
            String tableIdCode = orgBean.getStr("ORG_FIELD_PK");
            String accountUserStatusField = orgBean.getStr("ORG_ACCOUNT_STATUS");
            if (Strings.isNullOrEmpty(tableCode) || Strings.isNullOrEmpty(tableIdCode)) {
                throw new AccountException("Can't find the tableCode or pk code from the org mapping!");
            }
            DynaBean userBean = metaService.selectOne(tableCode, ConditionsWrapper.builder().in(tableIdCode, accountBean.getStr("USER_ASSOCIATION_ID")));
            if (userBean.getStr(accountUserStatusField).equals("0")) {
                if (accountIdSize == 1) {
                    throw new AccountException("该账号关联的员工已被禁用，请先启用访问状态！");
                } else {
                    throw new AccountException("该账号【" + accountBean.getStr("ACCOUNT_NAME") + "】关联的员工已被禁用，请先启用访问状态！");
                }
            }
        }
        return true;
    }

    @Override
    public void checkAccountUnique(String userId, int size) throws AccountException {
        DynaBean accountBean = metaService.selectOne("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("USER_ASSOCIATION_ID", userId));
        if (accountBean == null) {
            return;
        }

        //为空不进行校验
        if (!Strings.isNullOrEmpty(accountBean.getStr("ACCOUNT_CODE"))) {
            List<DynaBean> accountCodeBeanList = metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("ACCOUNT_CODE", accountBean.getStr("ACCOUNT_CODE")).ne("JE_RBAC_ACCOUNT_ID", accountBean.getStr("JE_RBAC_ACCOUNT_ID")));
            if (accountCodeBeanList != null && accountCodeBeanList.size() > 0) {
                if (size > 1) {
                    throw new AccountException("该数据" + accountBean.getStr("ACCOUNT_CODE") + "的账号重复，请修改！");
                } else {
                    throw new AccountException("该数据的账号重复，请修改！");
                }
            }
        }
        //为空不进行校验
        if (!Strings.isNullOrEmpty(accountBean.getStr("ACCOUNT_PHONE"))) {
            List<DynaBean> accountPhoneBeanList = metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("ACCOUNT_PHONE", accountBean.getStr("ACCOUNT_PHONE")).ne("JE_RBAC_ACCOUNT_ID", accountBean.getStr("JE_RBAC_ACCOUNT_ID")));
            if (accountPhoneBeanList != null && accountPhoneBeanList.size() > 0) {
                if (size > 1) {
                    throw new AccountException("该数据" + accountBean.getStr("ACCOUNT_CODE") + "的手机号重复，请修改！");
                } else {
                    throw new AccountException("该数据的手机号重复，请修改！");
                }
            }
        }
        //为空不进行校验
        if (!Strings.isNullOrEmpty(accountBean.getStr("ACCOUNT_MAIL"))) {
            List<DynaBean> accountEmailBeanList = metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("ACCOUNT_MAIL", accountBean.getStr("ACCOUNT_MAIL")).ne("JE_RBAC_ACCOUNT_ID", accountBean.getStr("JE_RBAC_ACCOUNT_ID")));
            if (accountEmailBeanList != null && accountEmailBeanList.size() > 0) {
                if (size > 1) {
                    throw new AccountException("该数据" + accountBean.getStr("ACCOUNT_CODE") + "的邮箱重复，请修改！");
                } else {
                    throw new AccountException("该数据的邮箱重复，请修改！");
                }
            }
        }
    }

    @Override
    public void checkAccountCodeUnique(String accountId, String accountCode) throws AccountException {
        List<DynaBean> accountCodeBeanList = metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("ACCOUNT_CODE", accountCode).ne("JE_RBAC_ACCOUNT_ID", accountId));
        if (accountCodeBeanList != null && accountCodeBeanList.size() > 0) {
            throw new AccountException("该数据的账号已存在，请检查！");
        }
    }

    @Override
    public void checkAccountPhoneUnique(String accountId, String accountPhone) throws AccountException {
        List<DynaBean> accountPhoneBeanList = metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("ACCOUNT_PHONE", accountPhone).ne("JE_RBAC_ACCOUNT_ID", accountId));
        if (accountPhoneBeanList != null && accountPhoneBeanList.size() > 0) {
            throw new AccountException("该数据的手机号已存在，请检查！");
        }
    }

    @Override
    public void checkAccountEmailUnique(String accountId, String accountEmail) throws AccountException {
        List<DynaBean> accountEmailBeanList = metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("ACCOUNT_MAIL", accountEmail).ne("JE_RBAC_ACCOUNT_ID", accountId));
        if (accountEmailBeanList != null && accountEmailBeanList.size() > 0) {
            throw new AccountException("该数据的邮箱已存在，请检查！");
        }
    }


    @Override
    public boolean checkOrgTypeByAccountId(String accountId) throws AccountException {
        DynaBean accountBean = metaService.selectOne("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("JE_RBAC_ACCOUNT_ID", accountId));
        if (accountBean == null) {
            throw new AccountException("Can't find the account by id");
        }
        DynaBean orgBean = metaService.selectOne("JE_RBAC_ORG", ConditionsWrapper.builder().eq("JE_RBAC_ORG_ID", accountBean.getStr("SY_ORG_ID")));
        if (OrgType.DEPARTMENT_ORG_ID.getCode().equals(orgBean.getStr("JE_RBAC_ORG_ID"))) {
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int doRemove(String accountIds) {
        List<String> accountIdList = Splitter.on(",").splitToList(accountIds);
        disableUserAccessStatus(accountIdList);
        metaService.delete("JE_RBAC_ACCOUNTDEPT", ConditionsWrapper.builder().in("ACCOUNTDEPT_ACCOUNT_ID", accountIdList));
        metaService.delete("JE_RBAC_ACCOUNTROLE", ConditionsWrapper.builder().in("ACCOUNTROLE_ACCOUNT_ID", accountIdList));
        int count = metaService.delete("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().in("JE_RBAC_ACCOUNT_ID", accountIdList));
        return count;
    }

    /***
     * 删除账号-同步禁用人员访问状态
     * @param accountIdList
     */
    public void disableUserAccessStatus(List<String> accountIdList) {
        List<DynaBean> accountBeanList = metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().in("JE_RBAC_ACCOUNT_ID", accountIdList));
        if (accountBeanList == null) {
            throw new AccountException("Can't find the account by id");
        }
        List<String> userIdList = new ArrayList<>();
        List<String> orgIds = new ArrayList<>();
        for (DynaBean eachAccountBean : accountBeanList) {
            userIdList.add(eachAccountBean.getStr("USER_ASSOCIATION_ID"));
            orgIds.add(eachAccountBean.getStr("SY_ORG_ID"));
        }
        //禁用员工所有部门访问状态
        List<DynaBean> orgBeanList = metaService.select("JE_RBAC_ORG", ConditionsWrapper.builder().in("JE_RBAC_ORG_ID", orgIds));
        for (DynaBean accountBean : accountBeanList) {
            for (DynaBean eachOrgBean : orgBeanList) {
                if (accountBean.getStr("SY_ORG_ID").equals(eachOrgBean.getStr("JE_RBAC_ORG_ID"))) {
                    String tableCode = eachOrgBean.getStr("ORG_RESOURCETABLE_CODE");
                    String tableIdCode = eachOrgBean.getStr("ORG_FIELD_PK");
                    if (Strings.isNullOrEmpty(tableCode) || Strings.isNullOrEmpty(tableIdCode)) {
                        throw new AccountException("Can't find the tableCode or pk code from the org mapping!");
                    }
                    //获取访问状态
                    String accountAccessStatusField = eachOrgBean.getStr("ORG_ACCOUNTACCESS_STATUS");
                    DynaBean userBeans = metaService.selectOne(tableCode, ConditionsWrapper.builder().in(tableIdCode, accountBean.getStr("USER_ASSOCIATION_ID")));
                    if (userBeans != null) {
                        metaService.executeSql("UPDATE " + tableCode + " SET " + accountAccessStatusField + "='0'  WHERE " + tableIdCode + " IN ({0})", accountBean.getStr("USER_ASSOCIATION_ID"));
                        if (eachOrgBean.getStr("JE_RBAC_ORG_ID").equals(OrgType.DEPARTMENT_ORG_ID.getCode())) {
                            metaService.executeSql("UPDATE JE_RBAC_DEPTUSER SET SY_STATUS ='0'  WHERE JE_RBAC_USER_ID IN ({0})", accountBean.getStr("USER_ASSOCIATION_ID"));
                        }
                    }
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void dataSync() throws AccountException {
        List<DynaBean> accountBeanList = metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder());
        if (accountBeanList == null) {
            throw new AccountException("Can't find the account by id");
        }
        List<String> orgIds = new ArrayList<>();
        Map<String, Object> hasAccountMap = new HashMap<>();
        for (DynaBean eachAccountBean : accountBeanList) {
            hasAccountMap.put(eachAccountBean.getStr("USER_ASSOCIATION_ID"), eachAccountBean);
            orgIds.add(eachAccountBean.getStr("SY_ORG_ID"));
        }
        List<DynaBean> orgBeanList = metaService.select("JE_RBAC_ORG", ConditionsWrapper.builder().in("JE_RBAC_ORG_ID", orgIds));
        for (DynaBean accountBean : accountBeanList) {
            for (DynaBean eachOrgBean : orgBeanList) {
                if (accountBean.getStr("SY_ORG_ID").equals(eachOrgBean.getStr("JE_RBAC_ORG_ID"))) {
                    String tableCode = eachOrgBean.getStr("ORG_RESOURCETABLE_CODE");
                    String tableIdCode = eachOrgBean.getStr("ORG_FIELD_PK");
                    if (Strings.isNullOrEmpty(tableCode) || Strings.isNullOrEmpty(tableIdCode)) {
                        throw new AccountException("Can't find the tableCode or pk code from the org mapping!");
                    }
                    //获取映射字段，账号名称、账号手机、账号邮箱、账号头像,账号性别
                    String accountNameField = eachOrgBean.getStr("ORG_ACCOUNT_NAME");
                    String accountPhoneField = eachOrgBean.getStr("ORG_ACCOUNT_PHONE");
                    String accountEmailField = eachOrgBean.getStr("ORG_ACCOUNT_MAIL");
                    String accountAvatarField = eachOrgBean.getStr("ORG_ACCOUNT_AVATAR");
                    String accountSexField = eachOrgBean.getStr("ORG_ACCOUNT_SEX");
                    DynaBean userBeans = metaService.selectOne(tableCode, ConditionsWrapper.builder().in(tableIdCode, accountBean.getStr("USER_ASSOCIATION_ID")));
                    if (userBeans != null) {
                        metaService.executeSql(
                                "UPDATE JE_RBAC_ACCOUNT SET ACCOUNT_NAME={0},ACCOUNT_PHONE={1},ACCOUNT_MAIL={2},ACCOUNT_AVATAR={3} ,ACCOUNT_SEX={4} WHERE JE_RBAC_ACCOUNT_ID ={5}",
                                userBeans.getStr(accountNameField), userBeans.getStr(accountPhoneField), userBeans.getStr(accountEmailField), userBeans.getStr(accountAvatarField), userBeans.getStr(accountSexField), accountBean.getStr("JE_RBAC_ACCOUNT_ID"));
                    }
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void dataSave(HttpServletRequest request) throws AccountException {
        if (request.getAttribute("dynaBeans") != null && !Strings.isNullOrEmpty(request.getAttribute("dynaBeans").toString())) {
            List<Map<String, Object>> beanList = (List<Map<String, Object>>) request.getAttribute("dynaBeans");
            for (Map<String, Object> objectMap : beanList) {
                if (objectMap.get("JE_RBAC_ACCOUNT_ID") != null && !objectMap.get("JE_RBAC_ACCOUNT_ID").equals("")) {
                    metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET ACCOUNT_REMARK={0},ACCOUNT_EXPIRE_TIME={1},ACCOUNT_PERMANENT_CODE={2}, WHERE JE_RBAC_ACCOUNT_ID ={3}", objectMap.get("ACCOUNT_REMARK"), objectMap.get("ACCOUNT_EXPIRE_TIME"), objectMap.get("ACCOUNT_PERMANENT_CODE"), objectMap.get("JE_RBAC_ACCOUNT_ID"));
                } else {
                    throw new AccountException("请设置相关参数！");
                }
            }
        } else {
            throw new AccountException("请设置相关参数！");
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void insertAccountDept(String accountId, String departmentId, String status) throws AccountException {
        DynaBean departmentBean = metaService.selectOne("JE_RBAC_DEPARTMENT", ConditionsWrapper.builder().eq("JE_RBAC_DEPARTMENT_ID", departmentId));
        if (departmentBean == null) {
            throw new AccountException("不存在的部门！");
        }
        DynaBean accountDeptBean = metaService.selectOne("JE_RBAC_ACCOUNTDEPT", ConditionsWrapper.builder()
                .eq("ACCOUNTDEPT_DEPT_ID", departmentId).eq("ACCOUNTDEPT_ACCOUNT_ID", accountId));
        if (accountDeptBean == null) {
            accountDeptBean = new DynaBean("JE_RBAC_ACCOUNTDEPT", false);
            accountDeptBean.set("ACCOUNTDEPT_DEPT_ID", departmentId);
            accountDeptBean.set("ACCOUNTDEPT_DEPT_NAME", departmentBean.getStr("DEPARTMENT_NAME"));
            accountDeptBean.set("SY_CREATETIME", DateUtils.formatDateTime(new Date()));
            accountDeptBean.set("ACCOUNTDEPT_ACCOUNT_ID", accountId);
            accountDeptBean.set("SY_COMPANY_ID", departmentBean.getStr("SY_COMPANY_ID"));
            accountDeptBean.set("SY_COMPANY_NAME", departmentBean.getStr("SY_COMPANY_NAME"));
            accountDeptBean.set("SY_GROUP_COMPANY_ID", departmentBean.getStr("SY_GROUP_COMPANY_ID"));
            accountDeptBean.set("SY_GROUP_COMPANY_NAME", departmentBean.getStr("SY_GROUP_COMPANY_NAME"));
            accountDeptBean.set("SY_STATUS", status);
            metaService.insert(accountDeptBean);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateUserAvatar(String accountId, String avatar) throws AccountException {
        DynaBean accountBean = metaService.selectOne("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("JE_RBAC_ACCOUNT_ID", accountId));
        if (accountBean == null) {
            throw new AccountException("不存在的账号！");
        }
        if (Strings.isNullOrEmpty(accountBean.getStr("SY_ORG_ID"))) {
            throw new AccountException("账号关联机构参数设置有误！");
        }
        DynaBean orgBean = metaService.selectOne("JE_RBAC_ORG", ConditionsWrapper.builder().eq("JE_RBAC_ORG_ID", accountBean.getStr("SY_ORG_ID")));
        if (orgBean == null) {
            throw new AccountException("账号所属机构不存在！");
        }
        //获取到映射的资源表和资源表主键
        String tableCode = orgBean.getStr("ORG_RESOURCETABLE_CODE");
        String tableIdCode = orgBean.getStr("ORG_FIELD_PK");
        if (Strings.isNullOrEmpty(tableCode) || Strings.isNullOrEmpty(tableIdCode)) {
            throw new AccountException("Can't find the tableCode or pk code from the org mapping!");
        }
        DynaBean userBean = metaService.selectOne(tableCode, ConditionsWrapper.builder().in(tableIdCode, accountBean.getStr("USER_ASSOCIATION_ID")));
        if (userBean == null) {
            throw new AccountException("不存在的人员！");
        }
        metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET ACCOUNT_AVATAR={0} WHERE JE_RBAC_ACCOUNT_ID ={1}", avatar, accountBean.getStr("JE_RBAC_ACCOUNT_ID"));
        if (accountBean.getStr("SY_ORG_ID").equals(OrgType.DEPARTMENT_ORG_ID.getCode())) {
            //公司员工-机构
            metaService.executeSql("UPDATE JE_RBAC_USER SET USER_AVATAR={0} WHERE JE_RBAC_USER_ID ={1}", avatar, userBean.getStr("JE_RBAC_USER_ID"));
        } else {
            //外部机构
            metaService.executeSql("UPDATE JE_RBAC_USER SET USER_AVATAR={0} WHERE JE_RBAC_USER_ID ={1}", avatar, userBean.getStr(tableIdCode));
        }
    }

    /**
     * 根据ID查找账号模型
     *
     * @param id 账户ID
     * @return
     */
    @Override
    public Account buildAccountModelById(String id, RealOrganizationUser realUser, List<Role> roles, Set<String> permissions) throws AccountException {
        DynaBean accountBean = accountRpcService.findAccountById(id);
        if (accountBean == null) {
            return null;
        }
        return buildAccountModel(accountBean, realUser, roles, permissions);
    }

    /**
     * 根据账户类型和账户查找账户
     *
     * @param account
     * @param realUser
     * @param roles
     * @param permissions
     * @return
     */
    @Override
    public Account buildAccountModelByType(String type, String account, RealOrganizationUser realUser, List<Role> roles, Set<String> permissions) throws AccountException {
        DynaBean accountBean = accountRpcService.findAccountByType(type, account);
        if (accountBean == null) {
            return null;
        }
        return buildAccountModel(accountBean, realUser, roles, permissions);
    }

    /**
     * 构建账号model
     *
     * @param accountBean 账户Bean
     * @param realUser    真实用户
     * @param roles       真实人员角色
     * @param permissions 权限集合
     * @return
     */
    @Override
    public Account buildAccountModel(DynaBean accountBean, RealOrganizationUser realUser, List<Role> roles, Set<String> permissions) throws AccountException {
        String orgId = accountBean.getStr("SY_ORG_ID");
        if (Strings.isNullOrEmpty(orgId)) {
            throw new AccountException("Can't find the account org!");
        }
        PlatformOrganization platformOrganization = findOrganizationById(orgId);
        Account account = new Account(platformOrganization, realUser, roles, permissions);
        account.parse(accountBean.getValues());
        if (realUser != null) {
            account.getRealUser().setDeptmentUserId(findDeptIdByAccountId(accountBean.getStr("JE_RBAC_ACCOUNT_ID"), account.getRealUser().getOrganization().getId()));
            account.setDeptId(findDeptIdByAccountId(accountBean.getStr("JE_RBAC_ACCOUNT_ID"), account.getRealUser().getOrganization().getId()));
        }
        return account;
    }

    private String findDeptIdByAccountId(String accountId, String orgId) {
        DynaBean countDept = metaService.selectOne("JE_RBAC_VACCOUNTDEPT", ConditionsWrapper.builder().eq("JE_RBAC_ACCOUNT_ID",
                accountId).eq("ACCOUNTDEPT_DEPT_ID", orgId));
        if (countDept == null) {
            return accountId;
        }
        return countDept.getStr("JE_RBAC_ACCOUNTDEPT_ID");
    }

    @Override
    public List<DynaBean> findByTenantId(String tenantId) {
        return metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().eq("SY_TENANT_ID", tenantId));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void recoverPassword(String accountIds) throws AccountException {
        List<String> accountIdList = Arrays.asList(accountIds.split(ArrayUtils.SPLIT));
        String defaultPassword = systemSettingRpcService.findSettingValue("JE_SYS_PASSWORD");
        metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET ACCOUNT_PASSWORD={0} WHERE JE_RBAC_ACCOUNT_ID IN ({1})", SecureUtil.md5(defaultPassword), accountIdList);
    }

    @Override
    public List<Map<String, Object>> requireOnlineUsers(String keyword, int start, int limit) {
        List<String> onlineUserIdList = authLoginManager.searchSessionId(keyword, start, limit);
        return metaService.selectSql("SELECT ACCOUNT_NAME,ACCOUNT_CODE,ACCOUNT_PHONE,ACCOUNT_MAIL,ACCOUNT_AVATAR,ACCOUNT_CARDNUM,SY_ORG_ID FROM JE_RBAC_ACCOUNT WHERE JE_RBAC_ACCOUNT_ID IN {0}", onlineUserIdList);
    }

    @Override
    public String validPassword(String password) {
        String result = null;
        String num = systemSettingRpcService.findSettingValue("REGEXP_NUMBER");
        if (Strings.isNullOrEmpty(num)) {
            num = "6";
        }
        String regexp = systemSettingRpcService.findSettingValue("REGEXP");
        if (("complex".equals(regexp) && !validComplex(password, num))) {
            result = "需要数字+大小写字母+特殊字符！";
        }
        if (("common".equals(regexp) && !validMedium(password, num))) {
            result = "需要数字+大小写字母！";
        }
        if (("simple".equals(regexp) && !validSimple(password, num))) {
            result = "需要数字+小写字母！";
        }
        return result;
    }

    /**
     * 校验复杂
     *
     * @param password
     * @param num
     * @return
     */
    @Override
    public boolean validComplex(String password, String num) {
        Pattern r = Pattern.compile("^(?=.*[$@$!%*#?&_^+])(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d$@$!%*#?&_^+]{" + num + ",}$");
        return r.matcher(password).find();
    }

    /**
     * 校验中等
     *
     * @param password
     * @param num
     * @return
     */
    @Override
    public boolean validMedium(String password, String num) {
        if (validComplex(password, num)) {
            return true;
        }
        Pattern r = Pattern.compile("^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{" + num + ",}$");
        return r.matcher(password).find();
    }

    /**
     * 校验简单
     *
     * @param password
     * @param num
     * @return
     */
    @Override
    public boolean validSimple(String password, String num) {
        if (validMedium(password, num)) {
            return true;
        }
        Pattern r = Pattern.compile("^(?=.*[a-z])(?=.*\\d)[a-z\\d]{" + num + ",}$");
        return r.matcher(password).find();
    }

    @Override
    public List<String> findAccountRoles(String tenantId, String accountId) {
        ConditionsWrapper wrapper = ConditionsWrapper.builder().eq("ACCOUNTROLE_ACCOUNT_ID", accountId);
        if (!Strings.isNullOrEmpty(tenantId)) {
            wrapper.eq("SY_TENANT_ID", tenantId);
        }

        List<DynaBean> accountRoleBeanList = metaService.select("JE_RBAC_ACCOUNTROLE", wrapper);
        if (accountRoleBeanList == null || accountRoleBeanList.isEmpty()) {
            return null;
        }
        List<String> roleList = new ArrayList<>();
        for (DynaBean eachBean : accountRoleBeanList) {
            roleList.add(eachBean.getStr("ACCOUNTROLE_ROLE_ID"));
        }
        return roleList;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void lockAccount(String accountIds, long disableTime) {
        List<String> accountIdList = Arrays.asList(accountIds.split(ArrayUtils.SPLIT));
        if (disableTime > 0) {
            String dateTimeStr = DateUtils.formatDateTime(new Date(System.currentTimeMillis() + disableTime * 1000));
            metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET ACCOUNT_LOCKED_STATUS='0',ACCOUNT_LOCK_EXPIRE={0} WHERE JE_RBAC_ACCOUNT_ID IN ({1})", dateTimeStr, accountIdList);
        } else {
            metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET ACCOUNT_LOCKED_STATUS='0' WHERE JE_RBAC_ACCOUNT_ID IN ({0})", accountIdList);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void unlockAccount(String accountIds) {
        List<String> accountIdList = Arrays.asList(accountIds.split(ArrayUtils.SPLIT));
        metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET ACCOUNT_LOCKED_STATUS ='1' , ACCOUNT_LOCK_EXPIRE = '' WHERE JE_RBAC_ACCOUNT_ID IN ({0})", accountIdList);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void disableAccount(String accountIds) throws AccountException {
        List<String> accountIdList = Arrays.asList(accountIds.split(ArrayUtils.SPLIT));
        List<DynaBean> accountBeanList = metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().in("JE_RBAC_ACCOUNT_ID", accountIdList));
        if (accountBeanList == null) {
            throw new AccountException("Can't find the account by id");
        }
        for (DynaBean eachBean : accountBeanList) {
            DynaBean orgBean = metaService.selectOne("JE_RBAC_ORG", ConditionsWrapper.builder().eq("JE_RBAC_ORG_ID", eachBean.getStr("SY_ORG_ID")));
            if (orgBean.getStr("JE_RBAC_ORG_ID").equals(OrgType.DEPARTMENT_ORG_ID.getCode())) {
                metaService.executeSql("UPDATE JE_RBAC_DEPTUSER SET SY_STATUS='0' WHERE  JE_RBAC_USER_ID IN ({0})", eachBean.getStr("USER_ASSOCIATION_ID"));
                metaService.executeSql("UPDATE JE_RBAC_USER SET SY_STATUS='0' WHERE JE_RBAC_USER_ID IN ({0})", eachBean.getStr("USER_ASSOCIATION_ID"));
                metaService.executeSql("UPDATE JE_RBAC_ACCOUNTDEPT SET SY_STATUS='0' WHERE ACCOUNTDEPT_ACCOUNT_ID IN ({0}) ", accountIdList);
                metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET SY_STATUS='0' WHERE JE_RBAC_ACCOUNT_ID IN ({0})", accountIdList);
            } else {
                //外部机构用户访问同步 允许访问
                String tableCode = orgBean.getStr("ORG_RESOURCETABLE_CODE");
                String tableIdCode = orgBean.getStr("ORG_FIELD_PK");
                String accountAccessStatusField = orgBean.getStr("ORG_ACCOUNTACCESS_STATUS");
                metaService.executeSql("UPDATE " + tableCode + " SET " + accountAccessStatusField + "='0'  WHERE " + tableIdCode + " = {0} ", eachBean.getStr("USER_ASSOCIATION_ID"));
                metaService.executeSql("UPDATE JE_RBAC_ACCOUNTDEPT SET SY_STATUS='0' WHERE ACCOUNTDEPT_ACCOUNT_ID IN ({0}) ", accountIdList);
                metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET SY_STATUS='0' WHERE JE_RBAC_ACCOUNT_ID IN ({0})", accountIdList);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void enableAccount(String accountIds) throws AccountException {
        List<String> accountIdList = Arrays.asList(accountIds.split(ArrayUtils.SPLIT));
        List<DynaBean> accountBeanList = metaService.select("JE_RBAC_ACCOUNT", ConditionsWrapper.builder().in("JE_RBAC_ACCOUNT_ID", accountIdList));
        if (accountBeanList == null) {
            throw new AccountException("Can't find the account by id");
        }
        for (DynaBean eachBean : accountBeanList) {
            DynaBean orgBean = metaService.selectOne("JE_RBAC_ORG", ConditionsWrapper.builder().eq("JE_RBAC_ORG_ID", eachBean.getStr("SY_ORG_ID")));
            if (checkUserStatusByAccountId(eachBean.getStr("JE_RBAC_ACCOUNT_ID"), accountBeanList.size())) {
                if (orgBean.getStr("JE_RBAC_ORG_ID").equals(OrgType.DEPARTMENT_ORG_ID.getCode())) {
                    List<DynaBean> userDeptBeanList = metaService.select("JE_RBAC_DEPTUSER", ConditionsWrapper.builder().in("JE_RBAC_USER_ID", eachBean.getStr("USER_ASSOCIATION_ID")));

                    List<String> deptIdsList = new ArrayList<>();
                    for (DynaBean userDept : userDeptBeanList) {
                        deptIdsList.add(userDept.getStr("JE_RBAC_DEPARTMENT_ID"));
                    }
                    if (deptIdsList != null && deptIdsList.size() > 0) {
                        //启用账号，启用该账号所有部门人员，若该部门人员为开通允许，则生成账号逻辑并启用
                        for (String deptId : deptIdsList) {
                            DynaBean accountDeptBean = metaService.selectOne("JE_RBAC_ACCOUNTDEPT", ConditionsWrapper.builder().eq("ACCOUNTDEPT_DEPT_ID", deptId).eq("ACCOUNTDEPT_ACCOUNT_ID", eachBean.getStr("JE_RBAC_ACCOUNT_ID")));
                            if (accountDeptBean == null) {
                                //新增账号部门
                                insertAccountDept(eachBean.getStr("JE_RBAC_ACCOUNT_ID"), deptId, "0");
                            }
                        }
                        metaService.executeSql("UPDATE JE_RBAC_DEPTUSER SET SY_STATUS='1' WHERE  JE_RBAC_USER_ID = {0} AND JE_RBAC_DEPARTMENT_ID IN ({1})", eachBean.getStr("USER_ASSOCIATION_ID"), deptIdsList);
                        metaService.executeSql("UPDATE JE_RBAC_ACCOUNTDEPT SET SY_STATUS='1' WHERE ACCOUNTDEPT_ACCOUNT_ID = {0} AND ACCOUNTDEPT_DEPT_ID IN ({1})", eachBean.getStr("JE_RBAC_ACCOUNT_ID"), deptIdsList);
                        metaService.executeSql("UPDATE JE_RBAC_USER SET SY_STATUS='1' WHERE JE_RBAC_USER_ID IN ({0})", eachBean.getStr("USER_ASSOCIATION_ID"));
                        metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET SY_STATUS='1' WHERE JE_RBAC_ACCOUNT_ID IN ({0})", eachBean.getStr("JE_RBAC_ACCOUNT_ID"));
                    }
                } else {
                    //外部机构用户访问同步 允许访问
                    String tableCode = orgBean.getStr("ORG_RESOURCETABLE_CODE");
                    String tableIdCode = orgBean.getStr("ORG_FIELD_PK");
                    String accountAccessStatusField = orgBean.getStr("ORG_ACCOUNTACCESS_STATUS");
                    metaService.executeSql("UPDATE " + tableCode + " SET " + accountAccessStatusField + "='1'  WHERE " + tableIdCode + " = {0} ", eachBean.getStr("USER_ASSOCIATION_ID"));
                    metaService.executeSql("UPDATE JE_RBAC_ACCOUNTDEPT SET SY_STATUS='1' WHERE ACCOUNTDEPT_ACCOUNT_ID = {0} AND ACCOUNTDEPT_DEPT_ID IN ({1})", eachBean.getStr("JE_RBAC_ACCOUNT_ID"), orgBean.getStr("JE_RBAC_ORG_ID"));
                    metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET SY_STATUS='1' WHERE JE_RBAC_ACCOUNT_ID IN ({0})", eachBean.getStr("JE_RBAC_ACCOUNT_ID"));
                }
            }
        }
    }

    @Override
    public List<Map<String, Object>> queryLoginStatistic(String year, String month) throws AccountException {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());

        if (Strings.isNullOrEmpty(month)) {
            month = String.valueOf(calendar.get(Calendar.MONTH) + 1);
        }
        month = String.format("%02d", Integer.valueOf(month));
        if (Strings.isNullOrEmpty(year)) {
            year = String.valueOf(calendar.get(Calendar.YEAR));
        }

        Map<String, Integer> result = new HashMap<>();
        List<Map<String, Object>> loginTimes = metaService.selectSql("select SY_ACCOUNT_ID,date_format(SY_CREATETIME, '%Y-%m-%d') as LOG_DATE,count(*) as LOG_NUM from je_rbac_loginlog where SY_CREATETIME like {0} group by SY_ACCOUNT_ID,date_format(SY_CREATETIME, '%Y-%m-%d') order by date_format(SY_CREATETIME, '%Y-%m-%d')", (year + "-" + month + "%"));

        for (Map<String, Object> eachMap : loginTimes) {
            String logdate = (String) eachMap.get("LOG_DATE");
            if (!result.containsKey(logdate)) {
                result.put(logdate, 1);
            } else {
                result.put(logdate, result.get(logdate) + 1);
            }
        }

        List<Map<String, Object>> resultListMap = new ArrayList<>();
        Map<String, Object> resultEntry;
        int monthCount = getMonthDays(Integer.valueOf(year), Integer.valueOf(month));
        try {
            for (int i = 0; i < monthCount; i++) {
                resultEntry = new HashMap<>();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Date date = new SimpleDateFormat("yyyy-MM-dd").parse(year + "-" + month + "-" + (i + 1));
                String dateStr = sdf.format(date);

                resultEntry.put(dateStr, 0);
                for (Map.Entry<String, Integer> entry : result.entrySet()) {
                    if (DateUtil.parseDate(entry.getKey()).getTime() == date.getTime()) {
                        resultEntry.put(entry.getKey(), entry.getValue());
                        break;
                    }
                }
                resultListMap.add(resultEntry);
            }
        } catch (ParseException e) {
            throw new AccountException("登录人次统计解析异常！");
        }
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (Map<String, Object> map : resultListMap) {
            resultEntry = new HashMap<>();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                resultEntry.put("dateStr", entry.getKey());
                resultEntry.put("count", entry.getValue());
            }
            resultList.add(resultEntry);
        }
        return resultList;
    }

    @Override
    public Map<String, Object> staffStatistic(String year) throws AccountException {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        if (Strings.isNullOrEmpty(year)) {
            year = String.valueOf(calendar.get(Calendar.YEAR));
        }

        List<DynaBean> accountObJobBeanList = metaService.select("JE_RBAC_ACCOUNTONJOB", ConditionsWrapper.builder().like("ACCOUNTONJOB_TJRQ", year));
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> resultEntryMap = new ArrayList<>();
        Map<String, Object> onJobMap;
        try {
            for (int i = 0; i < 12; i++) {
                Calendar cal = Calendar.getInstance();
                cal.setTime(new SimpleDateFormat("yyyy-MM").parse(year + "-" + (i + 1)));
                cal.set(Calendar.DAY_OF_MONTH, 1);
                cal.roll(Calendar.DAY_OF_MONTH, -1);
                String month = new SimpleDateFormat("yyyy-MM").format(cal.getTime());
                onJobMap = new HashMap<>();
                onJobMap.put("month", month);
                onJobMap.put("onJobCount", 0);
                for (DynaBean bean : accountObJobBeanList) {
                    if (month.equals(bean.get("ACCOUNTONJOB_TJRQ"))) {
                        onJobMap.put("onJobCount", bean.get("ACCOUNTONJOB_TJSL"));
                        break;
                    }
                }
                resultEntryMap.add(onJobMap);
            }
        } catch (ParseException e) {
            throw new AccountException("组织信息统计解析异常！");
        }
        result.put("entryStaffCount", resultEntryMap);
        return result;
    }

    @Override
    public void doSaveList(Object obj) {
        boolean isNull = false;
        try {
            JSONArray jsonArray = JSONArray.parseArray(obj.toString());
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                String id = jsonObject.get("id") == null ? "" : jsonObject.get("id").toString();
                String permanent = jsonObject.get("permanent") == null ? "" : jsonObject.get("permanent").toString();
                String secretCode = jsonObject.get("secretCode") == null ? "" : jsonObject.get("secretCode").toString();
                String secretName = jsonObject.get("secretName") == null ? "" : jsonObject.get("secretName").toString();
                String time = jsonObject.get("time") == null ? "" : jsonObject.get("time").toString();
                if (Strings.isNullOrEmpty(id)) {
                    continue;
                }
                if ((Strings.isNullOrEmpty(permanent) || "0".equals(permanent)) && Strings.isNullOrEmpty(time)) {
                    isNull = true;
                }

                metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET SY_SECRET_CODE='" + secretCode + "' , SY_SECRET_NAME = '" + secretName + "' WHERE JE_RBAC_ACCOUNT_ID = '" + id + "'");
                if (!Strings.isNullOrEmpty(permanent) && "1".equals(permanent)) {
                    metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET ACCOUNT_PERMANENT_CODE='" + permanent + "' , ACCOUNT_EXPIRE_TIME = '' WHERE JE_RBAC_ACCOUNT_ID = '" + id + "'");
                }
                if (!Strings.isNullOrEmpty(time)) {
                    metaService.executeSql("UPDATE JE_RBAC_ACCOUNT SET ACCOUNT_EXPIRE_TIME = '" + time + "' , ACCOUNT_PERMANENT_CODE='0' WHERE JE_RBAC_ACCOUNT_ID = '" + id + "'");
                }
            }
        } catch (Exception e) {
            throw new AccountException("保存失败，请联系管理员！");
        }
        if (isNull) {
            throw new AccountException("账号不可设置【 永久使用 】和【 过期时间 】同时为空！");
        }
    }

    @Override
    public void updateRoleName(String roleId, String roleName) {
        metaService.executeSql(String.format("UPDATE JE_RBAC_ACCOUNTROLE SET ACCOUNTROLE_ROLE_NAME='%s' WHERE ACCOUNTROLE_ROLE_ID='%s'"
                , roleName, roleId));
    }

    public static int getMonthDays(int year, int month) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, (month - 1));
        cal.set(Calendar.DATE, 1);
        cal.roll(Calendar.DATE, -1);
        return cal.getActualMaximum(Calendar.DATE);
    }

}
